﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace TemplateManager
{
    public class Template : ITemplate
    {
        private string projectName;
        private string guid;
        private string projectPath;

        public string ProjectName
        {
            get { return projectName; }
            set { projectName = value; }
        }

        public string ProjectPath
        {
            get { return projectPath; }
            set { projectPath = value; }
        }

        public string GUID
        {
            get { return guid; }
            set { guid = value; }
        }

        public Template() { }

        public Template(string templateName, string templatePath, string guid)
        {
            this.projectName = templateName;
            this.projectPath = templatePath;
            this.guid = guid;
        }

        public IProject CreateNewProject(string newProjectName, string newProjectPath)
        {
            if (Directory.Exists(ProjectPath))
            {
                string newGUID = Guid.NewGuid().ToString().ToUpper();

                DirectoryCopy(ProjectPath, newProjectPath + "\\" + newProjectName, true, newProjectName, newGUID);

                if (File.Exists(newProjectPath + "\\" + newProjectName + "\\" + this.ProjectName + ".sln"))
                    File.Move(newProjectPath + "\\" + newProjectName + "\\" + this.ProjectName + ".sln",
                        newProjectPath + "\\" + newProjectName + "\\" + newProjectName + ".sln");

                if (Directory.Exists(newProjectPath + "\\" + newProjectName + "\\" + this.ProjectName))
                    Directory.Move(newProjectPath + "\\" + newProjectName + "\\" + this.ProjectName,
                        newProjectPath + "\\" + newProjectName + "\\" + newProjectName);

                if (File.Exists(newProjectPath + "\\" + newProjectName + "\\" + newProjectName + "\\" + this.ProjectName + ".csproj"))
                    File.Move(newProjectPath + "\\" + newProjectName + "\\" + newProjectName + "\\" + this.ProjectName + ".csproj",
                        newProjectPath + "\\" + newProjectName + "\\" + newProjectName + "\\" + newProjectName + ".csproj");

                if (File.Exists(newProjectPath + "\\" + newProjectName + "\\" + newProjectName + "\\" + this.ProjectName + ".csproj.user"))
                    File.Move(newProjectPath + "\\" + newProjectName + "\\" + newProjectName + "\\" + this.ProjectName + ".csproj.user",
                        newProjectPath + "\\" + newProjectName + "\\" + newProjectName + "\\" + newProjectName + ".csproj.user");

                if (File.Exists(newProjectPath + "\\" + newProjectName + "\\" + this.ProjectName + ".csproj"))
                    File.Move(newProjectPath + "\\" + newProjectName + "\\" + this.ProjectName + ".csproj",
                        newProjectPath + "\\" + newProjectName + "\\" + newProjectName + ".csproj");

                if (File.Exists(newProjectPath + "\\" + newProjectName + "\\" + this.ProjectName + ".csproj.user"))
                    File.Move(newProjectPath + "\\" + newProjectName + "\\" + this.ProjectName + ".csproj.user",
                        newProjectPath + "\\" + newProjectName + "\\" + newProjectName + ".csproj.user");

                ConfigCSProjFile(newProjectPath + "\\" + newProjectName + "\\" + newProjectName + "\\" + newProjectName + ".csproj");
                ConfigCSProjFile(newProjectPath + "\\" + newProjectName + "\\" + newProjectName + "\\" + newProjectName + ".csproj.user");

                return new Template(newProjectName, newProjectPath, newGUID);
            }

            return null;
        }

        private void ConfigCSProjFile(string temppath)
        {
            if (File.Exists(temppath))
            {
                StreamReader reader = new StreamReader(File.OpenRead(temppath));
                string fileContent = reader.ReadToEnd();
                reader.Close();
                File.Delete(temppath);
                fileContent = fileContent.Substring(0, fileContent.IndexOf("</Project>")) + "</Project>";
                StreamWriter writer = new StreamWriter(File.OpenWrite(temppath));
                writer.Write(fileContent);
                writer.Close();
            }
        }

        //http://msdn.microsoft.com/en-us/library/bb762914.aspx
        private void DirectoryCopy(string sourceDirName, string destDirName, bool copySubDirs, string newProjectName, string newGUID)
        {
            // Get the subdirectories for the specified directory.
            DirectoryInfo dir = new DirectoryInfo(sourceDirName);
            DirectoryInfo[] dirs = dir.GetDirectories();

            if (!dir.Exists)
            {
                throw new DirectoryNotFoundException(
                    "Source directory does not exist or could not be found: "
                    + sourceDirName);
            }

            // If the destination directory doesn't exist, create it. 
            if (!Directory.Exists(destDirName))
            {
                Directory.CreateDirectory(destDirName);
            }

            // Get the files in the directory and copy them to the new location.
            FileInfo[] files = dir.GetFiles();
            foreach (FileInfo file in files)
            {
                string temppath = Path.Combine(destDirName, file.Name);
                file.CopyTo(temppath, false);

                if (file.Extension.Equals(".sln")
                    || file.Extension.Equals(".csproj")
                    || file.Extension.Equals(".cs")
                    || file.Extension.Equals(".cshtml")
                    || file.Extension.Equals(".config"))
                {
                    ChangeFileContent(temppath, newProjectName, newGUID);
                    Console.Out.WriteLine(temppath);
                }
            }

            // If copying subdirectories, copy them and their contents to new location. 
            if (copySubDirs)
            {
                foreach (DirectoryInfo subdir in dirs)
                {
                    string temppath = Path.Combine(destDirName, subdir.Name);
                    DirectoryCopy(subdir.FullName, temppath, copySubDirs, newProjectName, newGUID);
                }
            }
        }

        private void ChangeFileContent(string fileName, string ProjectName, string newGUID)
        {
            StreamReader reader = new StreamReader(File.OpenRead(fileName));
            string fileContent = reader.ReadToEnd();
            reader.Close();
            File.Delete(fileName);
            fileContent = fileContent.Replace(this.ProjectName, ProjectName);
            fileContent = fileContent.Replace(this.GUID, newGUID);
            StreamWriter writer = new StreamWriter(File.OpenWrite(fileName));
            writer.Write(fileContent);
            writer.Close();
        }

        public void AddFile(string sourceDirName)
        {
            string csproj = Path.Combine(this.ProjectPath, this.ProjectName, this.ProjectName, this.ProjectName + ".csproj");
            if (!File.Exists(csproj))
                csproj = Path.Combine(this.ProjectPath, this.ProjectName, this.ProjectName + ".csproj");
            string destDirName = new FileInfo(csproj).Directory.FullName;

            AddFile2(destDirName, sourceDirName);
        }

        private void AddFile2(string destDirName, string sourceDirName)
        {
            // Get the subdirectories for the specified directory.
            DirectoryInfo dir = new DirectoryInfo(sourceDirName);
            DirectoryInfo[] dirs = dir.GetDirectories();

            if (!dir.Exists)
            {
                throw new DirectoryNotFoundException(
                    "Source directory does not exist or could not be found: "
                    + sourceDirName);
            }

            // If the destination directory doesn't exist, create it. 
            if (!Directory.Exists(destDirName))
            {
                Directory.CreateDirectory(destDirName);
            }

            DirectoryInfo di = new DirectoryInfo(destDirName);

            // Get the files in the directory and copy them to the new location.
            FileInfo[] files = dir.GetFiles();
            foreach (FileInfo file in files)
            {
                string temppath = Path.Combine(destDirName, file.Name);
                if (File.Exists(temppath))
                    File.Delete(temppath);
                file.CopyTo(temppath, false);
                InsertReference(Path.Combine(destDirName, file.Name));
            }

            // If copying subdirectories, copy them and their contents to new location. 
            foreach (DirectoryInfo subdir in dirs)
            {
                string temppath = Path.Combine(destDirName, subdir.Name);
                AddFile2(temppath, subdir.FullName);
            }
        }

        public void InsertReference(string fileName)
        {
            if (File.Exists(fileName))
            {
                string csproj = Path.Combine(this.ProjectPath, this.ProjectName, this.ProjectName, this.ProjectName + ".csproj");
                if (!File.Exists(csproj))
                    csproj = Path.Combine(this.ProjectPath, this.ProjectName, this.ProjectName + ".csproj");
                if (File.Exists(csproj))
                {
                    StreamReader reader = new StreamReader(File.OpenRead(csproj));
                    string fileContent = reader.ReadToEnd();
                    reader.Close();

                    FileInfo f = new FileInfo(fileName);
                    string pathToAdd = Path.Combine(this.ProjectPath, this.ProjectName) + @"\";
                    string nameToAdd = f.FullName.Replace(pathToAdd, "");

                    if (fileContent.IndexOf(fileName) < 0)
                    {
                        int index = -1;
                        string insert = "";

                        if (!(nameToAdd.IndexOf(@"Content\Site.css") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\images\ui-bg_flat_0_aaaaaa_40x100.png") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\images\ui-bg_flat_75_ffffff_40x100.png") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\images\ui-bg_glass_55_fbf9ee_1x400.png") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\images\ui-bg_glass_65_ffffff_1x400.png") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\images\ui-bg_glass_75_dadada_1x400.png") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\images\ui-bg_glass_75_e6e6e6_1x400.png") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\images\ui-bg_glass_95_fef1ec_1x400.png") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\images\ui-bg_highlight-soft_75_cccccc_1x100.png") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\images\ui-icons_222222_256x240.png") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\images\ui-icons_2e83ff_256x240.png") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\images\ui-icons_454545_256x240.png") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\images\ui-icons_888888_256x240.png") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\images\ui-icons_cd0a0a_256x240.png") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\jquery.ui.accordion.css") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\jquery.ui.all.css") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\jquery.ui.autocomplete.css") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\jquery.ui.base.css") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\jquery.ui.button.css") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\jquery.ui.core.css") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\jquery.ui.datepicker.css") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\jquery.ui.dialog.css") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\jquery.ui.progressbar.css") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\jquery.ui.resizable.css") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\jquery.ui.selectable.css") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\jquery.ui.slider.css") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\jquery.ui.tabs.css") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\jquery.ui.theme.css") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\jquery-ui.css") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\minified\images\ui-bg_flat_0_aaaaaa_40x100.png") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\minified\images\ui-bg_flat_75_ffffff_40x100.png") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\minified\images\ui-bg_glass_55_fbf9ee_1x400.png") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\minified\images\ui-bg_glass_65_ffffff_1x400.png") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\minified\images\ui-bg_glass_75_dadada_1x400.png") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\minified\images\ui-bg_glass_75_e6e6e6_1x400.png") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\minified\images\ui-bg_glass_95_fef1ec_1x400.png") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\minified\images\ui-bg_highlight-soft_75_cccccc_1x100.png") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\minified\images\ui-icons_222222_256x240.png") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\minified\images\ui-icons_2e83ff_256x240.png") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\minified\images\ui-icons_454545_256x240.png") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\minified\images\ui-icons_888888_256x240.png") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\minified\images\ui-icons_cd0a0a_256x240.png") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\minified\jquery.ui.accordion.min.css") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\minified\jquery.ui.autocomplete.min.css") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\minified\jquery.ui.button.min.css") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\minified\jquery.ui.core.min.css") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\minified\jquery.ui.datepicker.min.css") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\minified\jquery.ui.dialog.min.css") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\minified\jquery.ui.progressbar.min.css") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\minified\jquery.ui.resizable.min.css") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\minified\jquery.ui.selectable.min.css") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\minified\jquery.ui.slider.min.css") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\minified\jquery.ui.tabs.min.css") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\minified\jquery.ui.theme.min.css") >= 0)
                            && !(nameToAdd.IndexOf(@"Content\themes\base\minified\jquery-ui.min.css") >= 0)
                            && !(nameToAdd.IndexOf(@"Controllers\AccountController.cs") >= 0)
                            && !(nameToAdd.IndexOf(@"Controllers\HomeController.cs") >= 0)
                            //&& !(nameToAdd.IndexOf(@"FluentNHibernate"><HintPath>lib\FluentNHibernate.dll</HintPath></Reference>
                            && !(nameToAdd.IndexOf(@"Global.asax") >= 0)
                            //&& !(nameToAdd.IndexOf(@"Global.asax.cs"><DependentUpon>Global.asax</DependentUpon></Compile>
                            //&& !(nameToAdd.IndexOf(@"Iesi.Collections"><HintPath>lib\Iesi.Collections.dll</HintPath></Reference>
                            && !(nameToAdd.IndexOf(@"Microsoft.CSharp") >= 0)
                            && !(nameToAdd.IndexOf(@"Models\AccountModels.cs") >= 0)
                            //&& !(nameToAdd.IndexOf(@"NHibernate"><HintPath>lib\NHibernate.dll</HintPath></Reference>
                            && !(nameToAdd.IndexOf(@"Properties\AssemblyInfo.cs") >= 0)
                            && !(nameToAdd.IndexOf(@"Scripts\jquery.unobtrusive-ajax.js") >= 0)
                            && !(nameToAdd.IndexOf(@"Scripts\jquery.unobtrusive-ajax.min.js") >= 0)
                            && !(nameToAdd.IndexOf(@"Scripts\jquery.validate.js") >= 0)
                            && !(nameToAdd.IndexOf(@"Scripts\jquery.validate.min.js") >= 0)
                            && !(nameToAdd.IndexOf(@"Scripts\jquery.validate.unobtrusive.js") >= 0)
                            && !(nameToAdd.IndexOf(@"Scripts\jquery.validate.unobtrusive.min.js") >= 0)
                            && !(nameToAdd.IndexOf(@"Scripts\jquery-1.7.1.js") >= 0)
                            && !(nameToAdd.IndexOf(@"Scripts\jquery-1.7.1.min.js") >= 0)
                            && !(nameToAdd.IndexOf(@"Scripts\jquery-ui-1.8.20.js") >= 0)
                            && !(nameToAdd.IndexOf(@"Scripts\jquery-ui-1.8.20.min.js") >= 0)
                            && !(nameToAdd.IndexOf(@"Scripts\MicrosoftAjax.debug.js") >= 0)
                            && !(nameToAdd.IndexOf(@"Scripts\MicrosoftAjax.js") >= 0)
                            && !(nameToAdd.IndexOf(@"Scripts\MicrosoftMvcAjax.debug.js") >= 0)
                            && !(nameToAdd.IndexOf(@"Scripts\MicrosoftMvcAjax.js") >= 0)
                            && !(nameToAdd.IndexOf(@"Scripts\MicrosoftMvcValidation.debug.js") >= 0)
                            && !(nameToAdd.IndexOf(@"Scripts\MicrosoftMvcValidation.js") >= 0)
                            && !(nameToAdd.IndexOf(@"Scripts\modernizr-2.5.3.js") >= 0)
                            && !(nameToAdd.IndexOf(@"System") >= 0)
                            && !(nameToAdd.IndexOf(@"System.ComponentModel.DataAnnotations") >= 0)
                            && !(nameToAdd.IndexOf(@"System.Configuration") >= 0)
                            && !(nameToAdd.IndexOf(@"System.Core") >= 0)
                            && !(nameToAdd.IndexOf(@"System.Data") >= 0)
                            && !(nameToAdd.IndexOf(@"System.Data.DataSetExtensions") >= 0)
                            && !(nameToAdd.IndexOf(@"System.Data.Entity") >= 0)
                            && !(nameToAdd.IndexOf(@"System.Drawing") >= 0)
                            && !(nameToAdd.IndexOf(@"System.EnterpriseServices") >= 0)
                            && !(nameToAdd.IndexOf(@"System.Runtime.Serialization") >= 0)
                            && !(nameToAdd.IndexOf(@"System.ServiceModel") >= 0)
                            && !(nameToAdd.IndexOf(@"System.ServiceModel.Web") >= 0)
                            && !(nameToAdd.IndexOf(@"System.Web") >= 0)
                            && !(nameToAdd.IndexOf(@"System.Web.Abstractions") >= 0)
                            && !(nameToAdd.IndexOf(@"System.Web.ApplicationServices") >= 0)
                            && !(nameToAdd.IndexOf(@"System.Web.DynamicData") >= 0)
                            && !(nameToAdd.IndexOf(@"System.Web.Entity") >= 0)
                            && !(nameToAdd.IndexOf(@"System.Web.Extensions") >= 0)
                            && !(nameToAdd.IndexOf(@"System.Web.Routing") >= 0)
                            && !(nameToAdd.IndexOf(@"System.Web.Services") >= 0)
                            && !(nameToAdd.IndexOf(@"System.Xml") >= 0)
                            && !(nameToAdd.IndexOf(@"System.Xml.Linq") >= 0)
                            && !(nameToAdd.IndexOf(@"Views\_ViewStart.cshtml") >= 0)
                            && !(nameToAdd.IndexOf(@"Views\Account\ChangePassword.cshtml") >= 0)
                            && !(nameToAdd.IndexOf(@"Views\Account\ChangePasswordSuccess.cshtml") >= 0)
                            && !(nameToAdd.IndexOf(@"Views\Account\LogOn.cshtml") >= 0)
                            && !(nameToAdd.IndexOf(@"Views\Account\Register.cshtml") >= 0)
                            && !(nameToAdd.IndexOf(@"Views\Home\About.cshtml") >= 0)
                            && !(nameToAdd.IndexOf(@"Views\Home\Index.cshtml") >= 0)
                            && !(nameToAdd.IndexOf(@"Views\Shared\_Layout.cshtml") >= 0)
                            && !(nameToAdd.IndexOf(@"Views\Shared\_LogOnPartial.cshtml") >= 0)
                            && !(nameToAdd.IndexOf(@"Views\Shared\Error.cshtml") >= 0)
                            && !(nameToAdd.IndexOf(@"Views\Web.config") >= 0)
                            && !(nameToAdd.IndexOf(@"Web.config") >= 0)
                            )
                        {
                            if (f.Extension.Equals(".svc.cs")
                                || f.Name.IndexOf(".svc.cs") > 0)
                            {
                                index = fileContent.LastIndexOf("<!--Compile-->");
                                insert = "<Compile Include=\"" + nameToAdd + "\" >\r\n"
                                    + "      <DependentUpon>" + f.Name.Replace(".svc.cs", ".svc") + "</DependentUpon>\r\n"
                                    + "    </Compile>\r\n    ";
                            }
                            else
                                if (f.Extension.Equals(".cs"))
                                {
                                    index = fileContent.LastIndexOf("<!--Compile-->");
                                    insert = "<Compile Include=\"" + nameToAdd + "\" />\r\n    ";
                                }
                                else
                                {
                                    index = fileContent.LastIndexOf("<!--Content-->");
                                    insert = "<Content Include=\"" + nameToAdd + "\" />\r\n    ";
                                }
                        }

                        if (index >= 0)
                        {
                            fileContent = fileContent.Insert(index, insert);
                            File.Delete(csproj);
                            StreamWriter writer = new StreamWriter(File.OpenWrite(csproj));
                            writer.Write(fileContent);
                            writer.Close();
                        }
                    }
                }
            }
        }
    }
}
